package indi.h.devmg.supervise.telnet;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import org.apache.commons.net.telnet.TelnetClient;
import org.apache.log4j.Logger;

import indi.h.devmg.util.IOUtil;

public class TelnetRuntime implements Closeable {
	final static Logger l = Logger.getLogger(TelnetRuntime.class);
	private String defaultCode;
	private Thread thread;
	private TelnetClient tc;
	private OutputStream o = null;
	private PrintStream p = null;
	private InputStream i = null;
	private BufferedReader bt = null;
	private CommandBack cb = null;
	public static String ERROR_READ_CLOSE = "error_read_close";
	public static String ERROR_CONNECT_FAIL = "error_connect_fail";
	public static String ERROR_WRITE_FAIL = "error_write_fail";

	public TelnetRuntime(String termtype) {
		this(termtype, "utf-8");
	}

	public TelnetRuntime(String termtype, String code) {
		tc = new TelnetClient(termtype);
		this.defaultCode = code;
	}

	protected void resetThread() {
		if (this.thread != null)
			this.thread.interrupt();
	}

	protected void createInput() throws UnsupportedEncodingException {
		if (i == null)
			i = this.tc.getInputStream();
		if (bt == null)
			bt = new BufferedReader(new InputStreamReader(i, defaultCode));
	}

	protected void createOutput() {
		if (o == null)
			o = this.tc.getOutputStream();
		if (p == null)
			p = new PrintStream(o, true);
	}

	/**
	 * 根据默认端口23,连接服务器
	 * 
	 * @param ip
	 *            ip地址
	 * @param c
	 *            服务器返回信息回调地址
	 */
	public void connect(String ip, CommandBack c) {
		connect(ip, 23, c);
	}

	/**
	 * 根据指定端口连接服务器
	 * 
	 * @param ip
	 *            ip地址
	 * @param port
	 *            端口
	 * @param c
	 *            服务器返回信息回调地址
	 */
	public void connect(String ip, int port, CommandBack c) {
		try {
			tc.connect(ip, port);
			createInput();
			if (c == null) {
				this.cb = new CommandBack() {

					@Override
					public void handle(String msg) {
						// TODO Auto-generated method stub
						System.out.println(msg);
					}

					@Override
					public void close() throws IOException {
						// TODO Auto-generated method stub

					}
				};
			} else
				this.cb = c;
			waitMsg(this.bt, this.cb);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			this.cb.handle(ERROR_CONNECT_FAIL);
			l.error(IOUtil.NO_NEED_HANDLE, e);
			try {
				close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}

	public void exec(String command) {
		try {
			if (tc == null)
				this.cb.handle(ERROR_CONNECT_FAIL);
			createOutput();
			p.println(command);
		} catch (Exception e) {
			// TODO: handle exception
			this.cb.handle(ERROR_WRITE_FAIL);
			l.error(IOUtil.NO_NEED_HANDLE, e);
			try {
				close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}

	public void waitMsg(BufferedReader b, CommandBack c) {
		resetThread();
		thread = new Thread() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				try {
					String line = b.readLine();
					while (line != null) {
						c.handle(line);
						line = b.readLine();
					}
				} catch (IOException e) {
					// TODO: handle exception
					if (isInterrupted())
						c.handle(ERROR_READ_CLOSE);
					l.error(IOUtil.NO_NEED_HANDLE, e);
					try {
						close();
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
			}
		};
		thread.start();
	}

	public interface CommandBack extends Closeable {
		public void handle(String msg);
	}

	@Override
	public void close() throws IOException {
		// TODO Auto-generated method stub
		resetThread();
		if (this.cb != null)
			this.cb.close();
		if (this.cb != null)
			this.tc.disconnect();
		this.cb = null;
		this.tc = null;
		IOUtil.close(this.getClass(), bt, i, p, o);
	}
}
